home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / ip / ppp / bkc-ppp / ppp_async.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-20  |  17.8 KB  |  623 lines

  1. /* ppp_async.c - Streams async functions Also does FCS
  2.     Copyright (C) 1990  Brad K. Clements, All Rights Reserved
  3.     fcstab and some ideas nicked from if_ppp.c from cmu. See copyright notice in if_ppp.h
  4.      and Readme.streams
  5. */
  6. #include <sys/types.h>
  7.  
  8. #include "ppp.h"
  9. #if NPPP > 0
  10. #define    STREAMS    1
  11. #define    DEBUGS    1
  12. #include <sys/param.h>
  13. #include <sys/stream.h>
  14. #include <sys/stropts.h>
  15. #include <sys/dir.h>
  16. #include <sys/signal.h>
  17. #include <sys/user.h>
  18. #include <sys/mbuf.h>
  19. #include <sys/socket.h>
  20. #include <net/if.h>
  21. #include <sys/if_ppp.h>
  22. #include <sys/ppp_str.h>
  23.  
  24. #ifdef    DEBUGS
  25. #include <sys/syslog.h>
  26. #define    DLOG(s,a)    if(ppp_async_debug) log(LOG_INFO, s, a)
  27. int    ppp_async_debug=0;
  28. #else
  29. #define    DLOG(s)    {}
  30. #endif
  31.  
  32. static    int    ppp_async_open(), ppp_async_close(), ppp_async_rput(), ppp_async_wput(),
  33.         ppp_async_wsrv(), ppp_async_rsrv();
  34.  
  35. static     struct    module_info    minfo ={
  36.     0xabcd,"ppp_async",0, INFPSZ, 16384, 4096
  37. };
  38.  
  39. static    struct    qinit    r_init = {
  40.     ppp_async_rput, ppp_async_rsrv, ppp_async_open, ppp_async_close, NULL, &minfo, NULL
  41. };
  42. static    struct    qinit    w_init = {
  43.     ppp_async_wput, ppp_async_wsrv, ppp_async_open, ppp_async_close, NULL, &minfo, NULL
  44. };
  45. struct    streamtab    ppp_asyncinfo = {
  46.     &r_init, &w_init, NULL, NULL, NULL
  47. };
  48.  
  49. /*
  50.  * FCS lookup table as calculated by genfcstab.
  51.  */
  52. static u_short fcstab[256] = {
  53.     0x0000,    0x1189,    0x2312,    0x329b,    0x4624,    0x57ad,    0x6536,    0x74bf,
  54.     0x8c48,    0x9dc1,    0xaf5a,    0xbed3,    0xca6c,    0xdbe5,    0xe97e,    0xf8f7,
  55.     0x1081,    0x0108,    0x3393,    0x221a,    0x56a5,    0x472c,    0x75b7,    0x643e,
  56.     0x9cc9,    0x8d40,    0xbfdb,    0xae52,    0xdaed,    0xcb64,    0xf9ff,    0xe876,
  57.     0x2102,    0x308b,    0x0210,    0x1399,    0x6726,    0x76af,    0x4434,    0x55bd,
  58.     0xad4a,    0xbcc3,    0x8e58,    0x9fd1,    0xeb6e,    0xfae7,    0xc87c,    0xd9f5,
  59.     0x3183,    0x200a,    0x1291,    0x0318,    0x77a7,    0x662e,    0x54b5,    0x453c,
  60.     0xbdcb,    0xac42,    0x9ed9,    0x8f50,    0xfbef,    0xea66,    0xd8fd,    0xc974,
  61.     0x4204,    0x538d,    0x6116,    0x709f,    0x0420,    0x15a9,    0x2732,    0x36bb,
  62.     0xce4c,    0xdfc5,    0xed5e,    0xfcd7,    0x8868,    0x99e1,    0xab7a,    0xbaf3,
  63.     0x5285,    0x430c,    0x7197,    0x601e,    0x14a1,    0x0528,    0x37b3,    0x263a,
  64.     0xdecd,    0xcf44,    0xfddf,    0xec56,    0x98e9,    0x8960,    0xbbfb,    0xaa72,
  65.     0x6306,    0x728f,    0x4014,    0x519d,    0x2522,    0x34ab,    0x0630,    0x17b9,
  66.     0xef4e,    0xfec7,    0xcc5c,    0xddd5,    0xa96a,    0xb8e3,    0x8a78,    0x9bf1,
  67.     0x7387,    0x620e,    0x5095,    0x411c,    0x35a3,    0x242a,    0x16b1,    0x0738,
  68.     0xffcf,    0xee46,    0xdcdd,    0xcd54,    0xb9eb,    0xa862,    0x9af9,    0x8b70,
  69.     0x8408,    0x9581,    0xa71a,    0xb693,    0xc22c,    0xd3a5,    0xe13e,    0xf0b7,
  70.     0x0840,    0x19c9,    0x2b52,    0x3adb,    0x4e64,    0x5fed,    0x6d76,    0x7cff,
  71.     0x9489,    0x8500,    0xb79b,    0xa612,    0xd2ad,    0xc324,    0xf1bf,    0xe036,
  72.     0x18c1,    0x0948,    0x3bd3,    0x2a5a,    0x5ee5,    0x4f6c,    0x7df7,    0x6c7e,
  73.     0xa50a,    0xb483,    0x8618,    0x9791,    0xe32e,    0xf2a7,    0xc03c,    0xd1b5,
  74.     0x2942,    0x38cb,    0x0a50,    0x1bd9,    0x6f66,    0x7eef,    0x4c74,    0x5dfd,
  75.     0xb58b,    0xa402,    0x9699,    0x8710,    0xf3af,    0xe226,    0xd0bd,    0xc134,
  76.     0x39c3,    0x284a,    0x1ad1,    0x0b58,    0x7fe7,    0x6e6e,    0x5cf5,    0x4d7c,
  77.     0xc60c,    0xd785,    0xe51e,    0xf497,    0x8028,    0x91a1,    0xa33a,    0xb2b3,
  78.     0x4a44,    0x5bcd,    0x6956,    0x78df,    0x0c60,    0x1de9,    0x2f72,    0x3efb,
  79.     0xd68d,    0xc704,    0xf59f,    0xe416,    0x90a9,    0x8120,    0xb3bb,    0xa232,
  80.     0x5ac5,    0x4b4c,    0x79d7,    0x685e,    0x1ce1,    0x0d68,    0x3ff3,    0x2e7a,
  81.     0xe70e,    0xf687,    0xc41c,    0xd595,    0xa12a,    0xb0a3,    0x8238,    0x93b1,
  82.     0x6b46,    0x7acf,    0x4854,    0x59dd,    0x2d62,    0x3ceb,    0x0e70,    0x1ff9,
  83.     0xf78f,    0xe606,    0xd49d,    0xc514,    0xb1ab,    0xa022,    0x92b9,    0x8330,
  84.     0x7bc7,    0x6a4e,    0x58d5,    0x495c,    0x3de3,    0x2c6a,    0x1ef1,    0x0f78
  85. };
  86.  
  87.  
  88. struct  ppp_async_info {
  89.     u_int    pai_flags;
  90. #define    PAI_FLAGS_INUSE        0x1
  91. #define    PAI_FLAGS_FLUSH        0x2
  92. #define    PAI_FLAGS_ESCAPED     0x4
  93. #define    PAI_FLAGS_COMPPROT    0x8
  94. #define    PAI_FLAGS_COMPAC    0x10
  95.  
  96.     u_long    pai_asyncmap;            /* current outgoing asyncmap */
  97.     int    pai_buffsize;            /* how big of an input buffer to alloc */
  98.     int    pai_buffcount;            /* how many chars currently in the input buffer */
  99.     u_short    pai_fcs;            /* the current fcs */
  100.     mblk_t    *pai_buffer;            /* pointer to the current buffer list */
  101.     mblk_t    *pai_bufftail;            /* pointer to the current input block */
  102. };
  103.  
  104. typedef    struct ppp_async_info    PAI;
  105.  
  106. static PAI pai[NPPP];        /* our private cache of async control structures */
  107.  
  108.  
  109.  
  110. static int
  111. ppp_async_open(q, dev, flag, sflag)
  112.     queue_t    *q;
  113.     dev_t    dev;
  114.     int    flag,
  115.         sflag;
  116. /* an open function might fail if we don't have any more pai elements left free 
  117.  
  118. */
  119.  
  120. {
  121.     register PAI    *p;
  122.     register int x;
  123.     int    s;
  124.  
  125.     if(!suser()) {
  126.         u.u_error = EPERM;
  127.         return(OPENFAIL);    /* only let the superuser or setuid root ppl open
  128.                         this module */
  129.     }
  130.     
  131.     if(q->q_ptr) {
  132.         u.u_error = EBUSY;
  133.         return(OPENFAIL);
  134.     }
  135.     s = splstr();
  136.     if(!q->q_ptr) {
  137.         for(x=0; x < NPPP; x++)     /* search for an empty PAI */
  138.             if(!(pai[x].pai_flags & PAI_FLAGS_INUSE))
  139.                 break;
  140.         if(x == NPPP)    {        /* all buffers in use */
  141.             splx(s);        /* restore processor state */
  142.             u.u_error = ENOBUFS;
  143.             return (OPENFAIL);
  144.         }
  145.         p = &pai[x];
  146.         DLOG("ppp_async%d: opening\n",x);
  147.     }
  148.     else {
  149.         p = (PAI *) q->q_ptr;
  150.         DLOG("ppp_async%d: reopen\n", (p-pai)/sizeof(PAI));
  151.     }
  152.     WR(q)->q_ptr = q->q_ptr =  (caddr_t) p;    /* point the write Q and this read Q to private data. */            
  153.     p->pai_flags = PAI_FLAGS_INUSE;
  154.     p->pai_asyncmap = 0xffffffff;        /* default async map */
  155.     p->pai_buffsize = PPP_MTU + sizeof(struct ppp_header) + 
  156.             sizeof(u_short);    /* how big of a buffer to alloc */
  157.     p->pai_buffcount = 0;            /* number of chars currently in buffer */
  158.     p->pai_buffer = NULL;
  159.     splx(s);
  160.     return(0);
  161. }
  162.  
  163. static int
  164. ppp_async_close(q)
  165.     queue_t    *q;            /* queue info */
  166. {
  167.     int    s;
  168.     register PAI     *p;
  169.  
  170.     s = splstr();
  171.     if(p = (PAI *) q->q_ptr) {
  172.         p->pai_flags = 0;    /* clear all flags */
  173.         if(p->pai_buffer) {    /* currently receiving some chars, discard the buffer */
  174.             freemsg(p->pai_buffer);
  175.             p->pai_buffer = NULL;
  176.         }
  177.         DLOG("ppp_async%d: closing\n",(p-pai)/sizeof(PAI));
  178.     }
  179.     splx(s);
  180.     return(0);            
  181. }
  182.  
  183.  
  184. static int
  185. ppp_async_wput(q, mp)
  186.     queue_t  *q;
  187.     register mblk_t *mp;
  188.  
  189. /* M_IOCTL processing is performed at this level. There is some weirdness here, but I couldn't
  190. think of an easier way to handle it.
  191.  
  192.    SIOCSIFASYNCMAP and SIOCGIFASYNCMAP is handled here.
  193.  
  194.    SIOCSIFCOMPAC and SIOCSIFCOMPPROT are both handled here, rather than jamming new flag bits
  195.    into the if_ interface.  However the upper ppp_if.c module will set COMPAC and
  196.    COMPPROT flags too, it just doesn't generate the IOACK.
  197.  
  198.    SIOCSIFMRU and SIOCGIFMRU (Max Receive Unit) are both handled here.
  199.    Rather than using the MTU to set the MRU, we have a seperate IOCTL for it.
  200.  
  201. */
  202. {
  203.  
  204.     register struct iocblk    *i;
  205.     register PAI    *p;
  206.     int    x;
  207.  
  208.     switch (mp->b_datap->db_type) {
  209.  
  210.         case     M_FLUSH :
  211.             if(*mp->b_rptr & FLUSHW)
  212.                 flushq(q, FLUSHDATA);
  213.             putnext(q, mp);        /* send it along too */
  214.             break;
  215.  
  216.         case    M_DATA :
  217.             putq(q, mp);    /* queue it for my service routine */
  218.             break;
  219.  
  220.         case    M_IOCTL :
  221.             i = (struct iocblk *) mp->b_rptr;
  222.             p =  (PAI *) q->q_ptr;
  223.             switch (i->ioc_cmd) {
  224.  
  225.                 case SIOCSIFCOMPAC :    /* enable or disable AC compression */
  226.                     if(i->ioc_count != sizeof(u_char)) {
  227.                         i->ioc_error = EINVAL;
  228.                         goto iocnak;
  229.                     }
  230.                     DLOG("ppp_async: SIFCOMPAC %d\n",*(u_char *) mp->b_cont->b_rptr);
  231.                     if( *(u_char *) mp->b_cont->b_rptr) 
  232.                         p->pai_flags |= PAI_FLAGS_COMPAC;
  233.                     else
  234.                         p->pai_flags &= ~PAI_FLAGS_COMPAC;
  235.                     i->ioc_count = 0;
  236.                     goto iocack;
  237.                 case SIOCSIFCOMPPROT:    /* enable or disable PROT  compression */
  238.                     if(i->ioc_count != sizeof(u_char)) {
  239.                         i->ioc_error = EINVAL;
  240.                         goto iocnak;
  241.                     }
  242.  
  243.                     DLOG("ppp_async: SIFCOMPPROT %d\n",*(u_char *) mp->b_cont->b_rptr);
  244.                     if( *(u_char *) mp->b_cont->b_rptr) 
  245.                         p->pai_flags |= PAI_FLAGS_COMPPROT;
  246.                     else
  247.                         p->pai_flags &= ~PAI_FLAGS_COMPPROT;
  248.                     i->ioc_count = 0;
  249.                     goto iocack;
  250.  
  251.  
  252.                 case SIOCSIFMRU     :
  253.                     if(i->ioc_count != sizeof(int)) {
  254.                         i->ioc_error = EINVAL;
  255.                         goto iocnak;
  256.                     }
  257.                     x = *(int *) mp->b_cont->b_rptr;
  258.                     if(x < PPP_MTU)
  259.                         x = PPP_MTU;
  260.                     x += sizeof(struct ppp_header) + sizeof(u_short);
  261.                     if(x > 4096) { /* couldn't allocb something this big */
  262.                         i->ioc_error = EINVAL;
  263.                         goto iocnak;
  264.                     }
  265.                     p->pai_buffsize = x;
  266.  
  267.                     i->ioc_count  = 0;
  268.                     goto iocack;
  269.                 case SIOCGIFMRU :
  270.                     if(mp->b_cont = allocb(sizeof(int), BPRI_MED)) {
  271.                         *(int *) mp->b_cont->b_wptr = 
  272.                             p->pai_buffsize - (sizeof(struct ppp_header) + 
  273.                             sizeof(u_short));
  274.                         mp->b_cont->b_wptr += i->ioc_count  = sizeof(int);
  275.                         goto iocack;
  276.                     }
  277.                     i->ioc_error = ENOSR;
  278.                     goto iocnak;
  279.  
  280.                 case SIOCGIFASYNCMAP :
  281.                     if(mp->b_cont = allocb(sizeof(u_long), BPRI_MED)) {
  282.                         *(u_long *) mp->b_cont->b_wptr = p->pai_asyncmap;
  283.                         mp->b_cont->b_wptr += i->ioc_count = sizeof(u_long);
  284.                         goto iocack;
  285.                     }
  286.                     i->ioc_error = ENOSR;
  287.                     goto iocnak;
  288.                         
  289.                 case SIOCSIFASYNCMAP :
  290.                     
  291.                     if(i->ioc_count != sizeof(u_long)) {
  292.                         i->ioc_error = EINVAL;
  293.                         goto iocnak;    /* ugh, goto */
  294.                     }
  295.                     DLOG("ppp_async: SIFASYNCMAP %lx\n",*(u_long *) mp->b_cont->b_rptr);
  296.     
  297.                     p->pai_asyncmap = *(u_long *) mp->b_cont->b_rptr;
  298.                     i->ioc_count = 0;
  299. iocack:;
  300.                     mp->b_datap->db_type = M_IOCACK;
  301.                     qreply(q,mp);
  302.                     break;
  303. iocnak:;
  304.                     i->ioc_count = 0;
  305.                     mp->b_datap->db_type = M_IOCNAK;
  306.                     qreply(q, mp);
  307.                     break;
  308.                 default:        /* unknown IOCTL call */
  309.                     putnext(q,mp);    /* pass it along */
  310.             }
  311.             break;        
  312.         default :
  313.             putnext(q,mp);    /* don't know what to do with this, so send it along*/
  314.     }
  315. }
  316.  
  317. static int
  318. ppp_async_wsrv(q)
  319.     queue_t    *q;
  320.  
  321. /* this is an incredibly ugly routine. If you see a better way of doing this, feel free
  322.    to improve it. I'm hoping that the buffer management routines are efficient, in terms
  323.    of dup'ing and adjusting message blocks. Hopefully we won't run out of small message
  324.     blocks. Perhaps some counters should be kept to record how efficient this routine
  325.    is, and how much break up of messages is required. 
  326.  
  327.    I'm not doing anything funny with stuffing PPP_ESCAPES into the actual data buffers.
  328.    If you get a lot of outgoing errors .. you might need to up your
  329.    NBLK4 parameter by quite a bit.... (see param.c)
  330. */
  331. {
  332.     register u_char    *cp;
  333.     register PAI    *p;
  334.     register u_short    fcs;
  335.     register mblk_t *mp;
  336.     u_char        *start, *stop,c;
  337.     mblk_t    *m1, *m0, *outgoing;
  338.  
  339.     while((mp = getq(q)) != NULL) {
  340.         /* we can only get M_DATA types into our Queue, due to our Put function */
  341.         if(!canput(q->q_next)) {
  342.             putbq(q, mp);
  343.             return;
  344.         }
  345.         if(msgdsize(mp) < (sizeof(u_char) + sizeof(u_short))) {    /* at least a protocol
  346.                                     and FCS required */
  347.             freemsg(mp);    /* discard the message */
  348.             putctl1(OTHERQ(q), M_CTL, IF_OUTPUT_ERROR);    /* indicate an output error */
  349.             continue;
  350.         }
  351.         m0 = mp;    /* remember first message block */
  352.         p = (PAI *) q->q_ptr;
  353.         outgoing = NULL;
  354.         fcs = PPP_INITFCS;
  355. #define    SPECIAL(p,c)    ((c) == PPP_FLAG) || ((c) == PPP_ESCAPE) ||  \
  356.                 ((c) < 0x20 && ((p)->pai_asyncmap & (1 << (c))))
  357.  
  358.         /* for each block in the message, scan between the start and stop
  359.             markers for escaped chars. dup the message block and chain in
  360.             the PPP_ESCAPE char and the PPP_TRANS'd character. Continue processing
  361.             for all of this data block, then for all remaining blocks
  362.         */
  363.         while(mp) {
  364.             start = mp->b_rptr;
  365.             stop = mp->b_wptr;
  366.             while(start < stop )     {
  367.                 for(cp = start; cp < stop; cp++) {
  368.                     if(SPECIAL(p,*cp))
  369.                         break;
  370.                     fcs = PPP_FCS(fcs, *cp);
  371.                 }
  372.                     
  373.                 if(cp - start) {
  374.                     /* dup the message block, up to len chars */
  375.                     m1 = dupb(mp);
  376.                     if(!m1)
  377.                         goto nobuffs;
  378.                      /* discard chars at front */
  379.                     adjmsg(m1, start - mp->b_rptr);
  380.  
  381.                     /* throw away remaining chars */
  382.                     adjmsg(m1,  cp - stop);
  383.                     if(outgoing)
  384.                         linkb(outgoing, m1);
  385.                     else
  386.                         outgoing = m1;
  387.                 } 
  388.                 if(cp < stop) {    /* a special char must follow */
  389.                     m1 = allocb(2 * sizeof(u_char),BPRI_LO);
  390.                     if(!m1)
  391.                         goto nobuffs;
  392.                     *m1->b_wptr++ = PPP_ESCAPE;
  393.                     *m1->b_wptr++ = *cp ^ PPP_TRANS;
  394.                     fcs = PPP_FCS(fcs, *cp);
  395.                     if(outgoing)
  396.                         linkb(outgoing, m1);
  397.                     else
  398.                         outgoing = m1;
  399.                 }
  400.                 else
  401.                     break;    /* no sense in doing another add and 
  402.                            compare */
  403.                 start = cp + 1;
  404.             }  /* end while start < stop */
  405.             mp = mp->b_cont;    /* look at the next block */
  406.         } /* end while(mp) */
  407.         m1 = allocb(sizeof(u_char) + 2 * sizeof(u_short), BPRI_LO);
  408.         if(!m1)
  409.             goto nobuffs;
  410.         fcs ^= 0xffff;            /* XOR the resulting FCS */
  411.         c = fcs & 0xff;
  412.         if(SPECIAL(p,c)) {
  413.             *m1->b_wptr++ = PPP_ESCAPE;
  414.             *m1->b_wptr++ = c ^ PPP_TRANS;
  415.         }
  416.         else
  417.             *m1->b_wptr++ = c;
  418.         c = fcs >> 8;
  419.         if(SPECIAL(p,c)) {
  420.             *m1->b_wptr++ = PPP_ESCAPE;
  421.             *m1->b_wptr++ = c ^ PPP_TRANS;
  422.         }
  423.         else
  424.             *m1->b_wptr++  = c;
  425.  
  426.         *m1->b_wptr++ = PPP_FLAG;    /* add trailing PPP_FLAG */
  427.         linkb(outgoing, m1);        /* gee, we better have an outgoing by now */
  428.         /* now we check to see if the lower queue has entries, if so, we assume
  429.             that we don't need a leading PPP_FLAG because these packets
  430.             will be sent back to back */
  431.         if(!qsize(q->q_next)) {    /* no entries in next queue, have to add a leading 
  432.                       PPP_FLAG */
  433.             m1 = allocb(sizeof(u_char), BPRI_LO);
  434.             if(!m1)
  435.                 goto nobuffs;
  436.             *m1->b_wptr++ = PPP_FLAG;
  437.             linkb(m1, outgoing);
  438.             outgoing = m1;
  439.         }
  440.         /* phew, ready to ship */
  441.         putnext(q, outgoing);
  442.         freemsg(m0);        /* discard original message block pointers */
  443.         continue;
  444. nobuffs:;    /* well, we ran out of memory somewhere */
  445.         if(outgoing)
  446.             freemsg(outgoing);        /* throw away what we have already */
  447.         putbq(q, m0);                /* put back the original message */
  448.         putctl1(OTHERQ(q), M_CTL, IF_OUTPUT_ERROR);
  449.         qenable(q);                /* reschedule ourselves for later */
  450.         return;
  451.     } /* end while(getq()) */
  452. }    /* end function */                    
  453.  
  454. static int
  455. ppp_async_rput(q, mp)
  456.     queue_t *q;
  457.     register mblk_t *mp;
  458. {
  459.  
  460.     switch (mp->b_datap->db_type) {
  461.  
  462.         case     M_FLUSH :
  463.             if(*mp->b_rptr & FLUSHR)
  464.                 flushq(q, FLUSHDATA);
  465.             putnext(q, mp);        /* send it along too */
  466.             break;
  467.  
  468.         case    M_DATA :
  469.             putq(q, mp);    /* queue it for my service routine */
  470.             break;
  471.  
  472.         default :
  473.             putnext(q,mp);    /* don't know what to do with this, so send it along*/
  474.     }
  475. }
  476.  
  477. static int
  478. ppp_async_rsrv(q)
  479.     queue_t    *q;
  480. {
  481.     register mblk_t *mp;
  482.     register PAI    *p;
  483.     register u_char    *cp,c;
  484.     mblk_t    *m0;
  485.  
  486.     p = (PAI *) q->q_ptr;
  487. #define    INPUT_ERROR(q)    putctl1(OTHERQ(q), M_CTL, IF_INPUT_ERROR)
  488. #define    STUFF_CHAR(p,c)    (*(p)->pai_bufftail->b_wptr++ = (c), (p)->pai_buffcount++)
  489. #define    FLUSHEM(q,p)    (INPUT_ERROR(q), (p)->pai_flags |= PAI_FLAGS_FLUSH)
  490.  
  491.     while((mp = getq(q)) != NULL) {
  492.         /* we can only get M_DATA types into our Queue, due to our Put function */
  493.         if(!canput(q->q_next)) {
  494.             putbq(q, mp);
  495.             return;
  496.         }
  497.         m0 = mp;    /* remember first message block */
  498.         for(; mp != NULL; mp = mp->b_cont) {    /* for each message block */
  499.             cp = mp->b_rptr;
  500.             while(cp < mp->b_wptr) {
  501.                 c = *cp++;
  502.                 if(c == PPP_FLAG) {
  503.                     p->pai_flags &= ~PAI_FLAGS_FLUSH;    /* clear flush indicater */
  504.                     
  505.                     if(p->pai_buffcount > sizeof(u_short)) { /* discard FCS */
  506.                         adjmsg(p->pai_buffer, -sizeof(u_short));
  507.                         p->pai_buffcount -= sizeof(u_short);
  508.                     }
  509.                     if(p->pai_buffcount < sizeof(struct ppp_header)) {
  510.                         if(p->pai_buffcount) {
  511.                             INPUT_ERROR(q);
  512.                             DLOG("ppp_async: short packet\n",0);
  513.                         }
  514.                         p->pai_buffcount = 0;
  515.                         continue;
  516.                     }
  517.                     if(p->pai_buffer) {
  518.                         if(p->pai_fcs == PPP_GOODFCS)
  519.                             putnext(q, p->pai_buffer);
  520.                         else {
  521.                             INPUT_ERROR(q);
  522.                             freemsg(p->pai_buffer);
  523.                             DLOG("ppp_async: FCS Error\n",0);
  524.                         /* we could be discarding this buffer because of data errors
  525.                            in which case we could have kept it, however we might
  526.                            also be discarding it because it was too small. so
  527.                            we throw it away and the next allocation will be the
  528.                            correct size
  529.                         */
  530.                         }
  531.                         p->pai_buffer = NULL;
  532.                         p->pai_buffcount  = 0;
  533.                         continue;
  534.                     }
  535.                 }     /* c == PPP_FLAG */
  536.                 else if (p->pai_flags & PAI_FLAGS_FLUSH)
  537.                     continue;            /* skipping chars */
  538.                 else if (c == PPP_ESCAPE) {
  539.                     p->pai_flags |= PAI_FLAGS_ESCAPED;
  540.                     continue;
  541.                 }
  542.  
  543.                 if(p->pai_flags & PAI_FLAGS_ESCAPED) {
  544.                     p->pai_flags &= ~PAI_FLAGS_ESCAPED;     /* clear esc flag */
  545.                     c ^= PPP_TRANS;        /* xor's are cool */
  546.                 }
  547.  
  548.                 /* here we check to see if we have a buffer. If we don't, we assume
  549.                    that this is the first char for the buffer, and we allocb one */
  550.  
  551.                 if(!p->pai_buffer) {
  552.                     /* we allocate buffer chains in blocks of ALLOCBSIZE */
  553.             
  554.                     if(!(p->pai_buffer = allocb(ALLOCBSIZE, BPRI_MED))) {
  555.                         FLUSHEM(q,p);
  556.                         continue;
  557.                         /* if we don't get a buffer, is there some way
  558.                            to recover and requeue later? rather than flushing
  559.                             the current packet... ? */
  560.                     }
  561.                     p->pai_bufftail = p->pai_buffer;
  562.                 }
  563.                 if(!p->pai_buffcount) {
  564.                     p->pai_fcs = PPP_INITFCS;
  565.                     if(c != PPP_ALLSTATIONS) {
  566.                         if(p->pai_flags & PAI_FLAGS_COMPAC) {
  567.                             STUFF_CHAR(p,PPP_ALLSTATIONS);
  568.                             STUFF_CHAR(p,PPP_UI);
  569.                         }
  570.                         else {
  571.                             DLOG("ppp_async: missed ALLSTATIONS\n",0);
  572.                             FLUSHEM(q,p);
  573.                             continue;
  574.                         }
  575.                     }
  576.                 } /* end if !p->pai_buffcount */
  577.                 if(p->pai_buffcount == 1 && c != PPP_UI) {
  578.                     DLOG("ppp_async: missed UI\n",0);
  579.                     FLUSHEM(q,p);
  580.                     continue;
  581.                 }
  582.                 if(p->pai_buffcount == 2 && (c & 1) == 1) {
  583.                     if(p->pai_flags & PAI_FLAGS_COMPPROT)
  584.                         STUFF_CHAR(p, 0);
  585.                     else {
  586.                         DLOG("ppp_async: bad protocol high byte\n",0);
  587.                         FLUSHEM(q,p);
  588.                         continue;
  589.                     }
  590.                 }
  591.                 if(p->pai_buffcount == 3 && (c & 1) == 0) {
  592.                     DLOG("ppp_async: bad protocol low byte\n",0);
  593.                     FLUSHEM(q,p);
  594.                     continue;
  595.                 }
  596.                 if(p->pai_buffcount >= p->pai_buffsize)    {    /* overrun */
  597.                     DLOG("ppp_async: too many chars in input buffer %d\n", p->pai_buffcount);
  598.                     FLUSHEM(q,p);
  599.                     continue;
  600.                 }
  601.                 /* determine if we have enough space in the buffer */
  602.                 if(p->pai_bufftail->b_wptr >= p->pai_bufftail->b_datap->db_lim) {
  603.                     if(p->pai_bufftail = allocb(ALLOCBSIZE, BPRI_MED)) 
  604.                         linkb(p->pai_buffer, p->pai_bufftail);
  605.                     else {
  606.                         DLOG("ppp_async: couldn't get buffer for tail\n",0);
  607.                         FLUSHEM(q,p);    /* discard all of it */
  608.                         continue;
  609.                     }
  610.                  }
  611.                 STUFF_CHAR(p,c);
  612.                 p->pai_fcs = PPP_FCS(p->pai_fcs, c);
  613.             } /* end while cp  < wptr */
  614.         }    /* end for each block */
  615.         /* discard this message now */
  616.         freemsg(m0);
  617.     }    /* end while  getq */
  618.  
  619. }
  620.  
  621.  
  622. #endif
  623.